#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <cstring>
#include <sys/types.h>
#include <sys/wait.h>

using namespace std;

void print_pending() {
    printf("当前进程pending表为: ");
    sigset_t pending;
    sigpending(&pending);
    for(int signo = 31; signo >= 1; --signo) {
        int ismem = sigismember(&pending, signo);
        if(ismem == -1) {
            perror("sigismember");
            exit(-1);
        }
        cout << ismem;
    }
    cout << endl;
}

void sigcb(int signum) {
    cout << "Caught signal: " << signum << endl;
}

int main() {
    sigset_t set, oldset;
    sigemptyset(&set);
    sigaddset(&set, 2);
    sigaddset(&set, 40);
    sigprocmask(SIG_SETMASK, &set, &oldset);
    
    struct sigaction act1;
    act1.sa_handler = sigcb;
    sigaction(2, &act1, nullptr);
    int c1 = 1;
    while(true) {
        if(c1 <= 2) {
            raise(2);
            printf("已经给当前进程发送了%d次2号信号...\n", c1);
            sleep(1);
        }
        print_pending();
        if(c1 == 3) {
            sigprocmask(SIG_SETMASK, &oldset, nullptr);
            printf("取消阻塞2号信号\n");
        }
        sleep(1);
        ++c1;
    }
    return 0;
}


// void handler(int signo) {
//     pid_t rid = -1;
//     while((rid = waitpid(-1, nullptr, WNOHANG)) > 0) {
//         cout << "Caught SIGINT, signo = " << signo << " waitchildid = " << rid <<  endl;
//     }
// }

// int main() {
//     signal(17, handler);
//     srand(time(nullptr));
//     for(int i= 0; i < 10; i++) {
//         pid_t pid = fork();
//         if (pid == 0) {
//             // child process
//             cout << "i am child process, pid = " << getpid() << " ppid = " << getppid() << endl;
//             sleep(rand() % 10);
//             exit(0);
//         }
//         cout << "child process quit" << endl;
//         sleep(rand() % 10);
//     }
//     // father process
//     while(1) {
//         cout << "i am father process, pid = " << getpid() << endl;
//         sleep(1);
//     }
//     return 0;
// }






// void printPending() {
//     sigset_t pending;
//     sigpending(&pending);
//     for(int signo = 31; signo >= 1; --signo) {
//         // 无法直接对该信号集使用位操作
//         // 而是要用接口
//         int ismem = sigismember(&pending, signo);
//         if(ismem == -1) {
//             perror("sigismember");
//             exit(-1); 
//         }
//         cout << ismem;
//     }
//     cout << endl;
// }


// //自定义捕捉信号
// void myhandler(int signo) {
//     cout << "catch a sign....., signo = " << signo << endl;
//     int cnt = 0;
//     while(true) {
//         printPending();
//         sleep(1);
//     }
// }

// void myhandler2(int signo) {
//     cout << "myhandler2 catch a sign....., signo = " << signo << " pid = " << getpid() << endl;
// }

// int main() {
//     signal(3, myhandler2);
//     //1. 定义sigaciotn对象
//     struct sigaction act, oldact;
//     //2. 初始化
//     memset(&act, 0, sizeof(act));
//     memset(&act, 0, sizeof(act));
//     //3. 对x信号进行捕捉，这里是2号信号
//     act.sa_handler = myhandler;
//     // 也可以对sa_mask字段进行设置
//     // 除了默认阻塞2号，也可以设置阻塞其它的
//     sigemptyset(&act.sa_mask);
//     sigaddset(&act.sa_mask, 2);

//     //4. 注册信号
//     if(sigaction(2, &act, &oldact) == -1) {
//         perror("sigaction");
//         exit(-1);
//     }

//     //5. 接收信号
//     while(true) {
//         cout << "i am a process, pid = " << getpid() << endl;
//         sleep(1);
//     }
//     return 0;
// }






// int main() {
//     //0. 对某个信号进行捕捉，在这里是2号信号
//     signal(2, myhandler);

//     //1. 定义系统提供的信号集类型
//     //newset用做修改信号集
//     //oldset用作保存修改前的信号集
//     sigset_t newset, oldset;

//     //2. 对其进行初始化
//     sigemptyset(&newset);
//     sigemptyset(&oldset);

//     //3. 屏蔽2号信号
//     sigaddset(&newset, 2);

//     //到目前位置都是在操作这个局部变量
//     //还没有对内核中该进程的信号集产生任何影响s

//     //4. 通过系统调用，修改进程的信号集
//     //这里选择直接把newset的内容拷贝给阻塞信号集
//     //同时用oldset保存修改前的信号集
//     if(sigprocmask(SIG_SETMASK, &newset, &oldset) == -1) {
//         perror("sigprocmask");
//         exit(-1);
//     }
    
//     //5. 循环利用系统调用获取内核的pengding表
//     sigset_t pending;
//     int cnt = 0;
//     while(true) {
//         sigpending(&pending);
//         // 6. 输出每一位
//         printPending(pending);
//         //7. 运行10秒后修改回原来的阻塞信号集
//         if(cnt == 10) {
//             sigprocmask(SIG_SETMASK, &oldset, nullptr);
//         }
//         ++cnt;
//         sleep(1);
//     }
//     return 0;
// }

// // 捕捉信号
// void myhandler(int signum) {
//     cout << "i have capture a signal, signum = " << signum << endl;
// }

// int main() {
//     sigset_t set;
//     // 捕捉2号
//     signal(2, myhandler);
//     int c = 0;
//     while(1) {
//         cout << "i am a process, pid = " << getpid() << endl;
//         if(c % 2) {
//             // 给调用进程也就是自己发送信号
//             raise(2);
//         }
//         ++c;
//         sleep(1);
//     }

//     return 0;
// }


// //参数不合法打印消息
// void Usage(const string& s) {
//     cout << s << "\n\t" << "signalnum pid\n" << endl;
// }

// // 通过命令行参数控制
// int main(int argc, char* argv[]) {
//     // 需要3个参数
//     if(argc != 3) {
//         Usage(argv[0]);
//         exit(-1);
//     }
//     int signalnum = stoi(argv[1]);
//     pid_t tarid = stoi(argv[2]);
//     int n = kill(tarid, signalnum);
//     if(n == -1) {
//         perror("kill err");
//         exit(-1);
//     }
//     cout << "send a signal success" << endl;
//     return 0;
// }